package com.rlz.base.weiget

import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import android.view.animation.LinearInterpolator
import com.rlz.base.R

/**
 * Created by RLZ
 * on 2021/3/16
 *
 */
class CNLoadingView @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = 0
) :
        View(context, attrs, defStyleAttr) {
    /**
     * 线圆角及宽度
     */
    private var mLineBold = 0

    /**
     * 线条开始颜色 默认白色
     */
    private var mStartColor = Color.parseColor("#90FFFFFF")

    /**
     * 线条结束颜色 默认灰色
     */
    private var mEndColor = Color.parseColor("#10FFFFFF")

    /**
     * view的宽度 高度
     */
    private var mWidth = 0

    /**
     * view的高度
     */
    private var mHeight = 0

    /**
     * 线条长度
     */
    private var mLineLength = 0

    /**
     * 线条个数 默认12条
     */
    private var mLineCount = 12

    /**
     * 背景画笔
     */
    private var mBgPaint: Paint? = null

    /**
     * 渐变颜色
     */
    private var mColors: IntArray? = null

    /**
     * 动画是否已开启
     */
    private var isAnimationStart = false

    /**
     * 开始index
     */
    private var mStartIndex = 0

    /**
     * 动画
     */
    private var mValueAnimator: ValueAnimator? = null

    /**
     * 初始化颜色
     */
    private fun initColor() {
        // 渐变色计算类
        val argbEvaluator = ArgbEvaluator()
        // 初始化对应空间
        mColors = IntArray(mLineCount)
        // 获取对应的线颜色 此处由于是白色起头 黑色结尾所以需要反过来计算 即线的数量到0的数量递减 对应的ValueAnimator 是从0到线的数量-1递增
        for (i in mLineCount downTo 1) {
            val alpha = i.toFloat() / mLineCount
            mColors!![mLineCount - i] = argbEvaluator.evaluate(alpha, mStartColor, mEndColor) as Int
        }
    }

    /**
     * 加载自定义的属性
     */
    private fun loadAttrs(context: Context, attrs: AttributeSet?) {
        val array = context.obtainStyledAttributes(attrs, R.styleable.CNLoadingView)
        mStartColor = array.getColor(R.styleable.CNLoadingView_startColor, mStartColor)
        mEndColor = array.getColor(R.styleable.CNLoadingView_endColor, mEndColor)
        mLineCount = array.getInt(R.styleable.CNLoadingView_lineCount, mLineCount)
        //TypedArray回收
        array.recycle()
    }

    /**
     * 初始化画笔
     */
    private fun initPaint() {
        mBgPaint = Paint()
        //使得画笔更加圆滑
        mBgPaint!!.isAntiAlias = true
        mBgPaint!!.strokeJoin = Paint.Join.ROUND
        mBgPaint!!.strokeCap = Paint.Cap.ROUND
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        // 获取view的宽度 默认40dp
        mWidth = getViewSize(dip2px(40f), widthMeasureSpec)
        // 获取view的高度 默认40dp
        mHeight = getViewSize(dip2px(40f), heightMeasureSpec)
        // 使宽高保持一致
        mWidth = Math.min(mWidth, mHeight)
        mHeight = mWidth
        // 获取线的长度
        mLineLength = mWidth / 6
        // 获取线圆角及宽度
        mLineBold = mWidth / mLineCount
        // 设置线的圆角及宽度
        mBgPaint!!.strokeWidth = mLineBold.toFloat()
        setMeasuredDimension(mWidth, mHeight)
    }

    fun dip2px(dpValue: Float): Int {
        val scale: Float =
                context.getResources().getDisplayMetrics().density
        return (dpValue * scale + 0.5f).toInt()
    }

    /**
     * 测量模式       表示意思
     * UNSPECIFIED  父容器没有对当前View有任何限制，当前View可以任意取尺寸
     * EXACTLY      当前的尺寸就是当前View应该取的尺寸
     * AT_MOST      当前尺寸是当前View能取的最大尺寸
     *
     * @param defaultSize 默认大小
     * @param measureSpec 包含测量模式和宽高信息
     * @return 返回View的宽高大小
     */
    private fun getViewSize(defaultSize: Int, measureSpec: Int): Int {
        var viewSize = defaultSize
        //获取测量模式
        val mode = MeasureSpec.getMode(measureSpec)
        //获取大小
        val size = MeasureSpec.getSize(measureSpec)
        when (mode) {
            MeasureSpec.UNSPECIFIED ->                 //如果没有指定大小，就设置为默认大小
                viewSize = defaultSize
            MeasureSpec.AT_MOST ->                 //如果测量模式是最大取值为size
                //我们将大小取最大值,你也可以取其他值
                viewSize = size
            MeasureSpec.EXACTLY ->                 //如果是固定的大小，那就不要去改变它
                viewSize = size
            else -> {
            }
        }
        return viewSize
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        // 获取半径
        val r = mWidth / 2
        // 绘制前先旋转一个角度，使最顶上开始位置颜色与开始颜色匹配
        canvas.rotate(360f / mLineCount, r.toFloat(), r.toFloat())
        for (i in 0 until mLineCount) {
            // 获取颜色下标
            val index = (mStartIndex + i) % mLineCount
            // 设置颜色
            mBgPaint!!.color = mColors!![index]
            // 绘制线条 mLineBold >> 1 == mLineBold / 2 使居中显示
            canvas.drawLine(
                    r.toFloat(),
                    (mLineBold shr 1).toFloat(),
                    r.toFloat(),
                    ((mLineBold shr 1) + mLineLength).toFloat(),
                    mBgPaint!!
            )
            // 旋转角度
            canvas.rotate(360f / mLineCount, r.toFloat(), r.toFloat())
        }
    }
    /**
     * 开始动画
     *
     * @param duration 动画时间
     */
    /**
     * 开始动画 时间为1800毫秒一次
     */
    @JvmOverloads
    fun startAnimation(duration: Int = 1800) {
        if (mValueAnimator == null) {
            mValueAnimator = ValueAnimator.ofInt(mLineCount, 0)
            with(mValueAnimator) {
                this?.duration = duration.toLong()
                this?.setTarget(0)
                this?.repeatCount = -1
                this?.interpolator = LinearInterpolator()
                this?.addUpdateListener { animation -> // 此处会回调3次 需要去除后面的两次回调
                    if (mStartIndex != animation.animatedValue as Int) {
                        mStartIndex = animation.animatedValue as Int
                        invalidate()
                    }
                }
                this?.start()
            }
        }
        isAnimationStart = true
    }

    /**
     * 结束动画
     */
    fun stopAnimation() {
        if (mValueAnimator != null) {
            mValueAnimator!!.cancel()
            isAnimationStart = false
        }
    }

    /**
     * 是否在动画中
     *
     * @return 是为 true 否则 false
     */
    fun isAnimationStart(): Boolean {
        return isAnimationStart
    }

    /**
     * 防止内存溢出 未结束动画并退出页面时，需使用此函数，或手动释放此view
     */
    fun detachView() {
        if (mValueAnimator != null) {
            mValueAnimator!!.cancel()
            mValueAnimator = null
            isAnimationStart = false
        }
    }

    init {
        loadAttrs(context, attrs)
        initPaint()
        initColor()
    }
}